<script setup lang="ts">
import { type PropType, computed, ref, watch } from 'vue'
import { EnumClassName, listEnums, EnumProps, appConfig } from '@idmy/core'
import { CheckboxGroup, Radio, RadioButton, RadioGroup, Checkbox, Select, SelectOption } from 'ant-design-vue'
import { debounce, isFunction } from 'lodash-es'

defineOptions({ name: 'Enum' })

const props = defineProps({
	appKey: { type: String },
	buttonStyle: { type: String as PropType<'solid' | 'outline'>, default: 'solid' },
	buttonType: { type: String as PropType<'button' | 'radio'>, default: 'radio' },
	clazz: { type: String as PropType<EnumClassName>, required: true },
	clearable: { type: Boolean, default: true },
	component: { type: String as PropType<'Select' | 'Radio' | 'Checkbox'>, default: 'Select' },
	direction: {
		type: String as PropType<'horizontal' | 'vertical'>,
		default: 'horizontal',
	},
	valueKey: { type: String },
	disabled: Boolean,
	filter: { type: Function as PropType<(item: EnumProps) => boolean> },
	colour: { type: Boolean, default: undefined },
	modelValue: [String, Number, Array],
	defaultValue: [String, Number, Array],
	multiple: Boolean,
	placeholder: { type: String, default: '请选择' },
})

const emit = defineEmits(['update:modelValue', 'change'])

const enums = listEnums(props.clazz, props.appKey)

watch(
	() => props.clazz,
	debounce(clazz => clazz && listEnums(clazz, props.appKey), 500)
)
// @ts-ignore
const data = computed(() => {
	if (enums.value.length) {
		const arr = isFunction(props.filter) ? enums.value.filter(row => props.filter?.(row)) : enums.value
		return arr.map((row: EnumProps) => ({
			color: row.color,
			key: row.key,
			label: row.formatTitle ?? row.title,
			title: row.title,
			// @ts-ignore
			value: row[props.valueKey ?? appConfig.enum.valueKey],
		}))
	} else {
		return []
	}
})

const model = ref<any>(props.defaultValue ?? props.modelValue)
watch(
	() => props.modelValue,
	val => {
		model.value = val
	}
)

const onChange = (val: any) => {
	emit('update:modelValue', val)
	if (val) {
		emit('change', enums.value[val])
	} else {
		emit('change', {})
	}
}

const isColour = (color?: string) => {
	if (!color) return false
	if (props.colour === true) {
		return true
	} else if (props.colour === undefined) {
		if (props.component === 'Radio' && props.buttonStyle === 'solid') {
			return false
		} else {
			return true
		}
	}
	return false
}
</script>

<template>
	<RadioGroup v-if="component === 'Radio'" v-model:value="model" :disabled="disabled" :button-style="buttonStyle" @change="onChange(model)">
		<template v-if="buttonType === 'button'">
			<RadioButton v-for="(item, idx) in data" :key="`${item.value}:${idx}`" :value="item.value">
				<slot name="name" v-bind="item">
					<span v-if="isColour(item.color)" :class="item.color">{{ item.label }}</span>
					<template v-else>
						{{ item.label }}
					</template>
				</slot>
			</RadioButton>
		</template>
		<Radio v-for="(item, idx) in data" v-else :key="`${item.value}:${idx}`" :value="item.value">
			<slot name="name" v-bind="item">
				<span v-if="isColour(item.color)" :class="item.color">{{ item.label }}</span>
				<template v-else>
					{{ item.label }}
				</template>
			</slot>
		</Radio>
	</RadioGroup>
	<CheckboxGroup v-else-if="component === 'Checkbox'" v-model:value="model" :disabled="disabled" @change="onChange(model)">
		<Checkbox v-for="(item, idx) in data" :key="`${item.value}:${idx}`" :value="item.value">
			<slot name="name" v-bind="item">
				<span v-if="isColour(item.color)" :class="item.color">{{ item.label }}</span>
				<template v-else>
					{{ item.label }}
				</template>
			</slot>
		</Checkbox>
	</CheckboxGroup>
	<Select
		v-else
		v-model:value="model"
		:mode="multiple ? 'multiple' : undefined"
		:disabled="disabled"
		:allow-clear="clearable"
		:placeholder="placeholder"
		show-search
		@change="onChange(model)"
	>
		<SelectOption v-for="(item, idx) in data" :key="`${item.value}:${idx}`" :value="item.value">
			<slot name="name" v-bind="item">
				<span v-if="isColour(item.color)" :class="item.color">{{ item.label }}</span>
				<template v-else>
					{{ item.label }}
				</template>
			</slot>
		</SelectOption>
	</Select>
</template>
